using System;
using System.Globalization;
using FireStarter.Base;
using Firestarter.DB.Schema.BO;
using FireStarterModeller.BO;
using Habanero.Base.Exceptions;

namespace Firestarter.DB_DomainModel.Logic
{
    public class DBToDMClassImporter : IDBToDMClassImporter
    {
        /// <summary>
        /// Returns the table prefix to be used for this transformation this prefix may be 
        ///  a prefix set up for this particular database, for this project, a global settings for all
        ///  projects for this user or a global setting for all users of an organisation. 
        /// </summary>
        /// <returns></returns>
        public virtual string TableNamePrefix { get; set; }

        /// <summary>
        /// Returns the primary key suffix to be used for this transformation this suffix may be 
        ///  a suffix set up for this particular database, for this project, a global settings for all
        ///  projects for this user or a global setting for all users of an organisation. 
        /// </summary>
        /// <returns></returns>
        public virtual string PrimaryKeyColumnSuffix { get; set; }

        /// <summary>
        /// Imports the data from the <paramref name="dbTable"/> into the <paramref name="dmSolution"/>.
        /// If hte dbTable's PendingChangeType is Delete then the related class is deleted.
        /// If the matching class does not exist and the PendingChangeType != delete then it is created.
        /// Else the matching class is updated.
        /// </summary>
        /// <param name="dmSolution"></param>
        /// <param name="dbTable"></param>
        /// <returns></returns>
        public DMClass Import(DMSolution dmSolution, IDBTable dbTable)
        {
            CheckSolution(dmSolution);

            if (dbTable == null) throw new ArgumentNullException("dbTable");
            DMClass foundDBClass = dbTable.GetMappedDMClass();
            if (foundDBClass != null)
            {
                UpdateClassDescription(dbTable, foundDBClass);
                UpdateClassName(dbTable, foundDBClass);
                foundDBClass.MappedTableName = dbTable.TableName;
                foundDBClass.MappedSchemaName = dbTable.SchemaName;

                return foundDBClass;
            }

            foundDBClass = dmSolution.FindClassByMappedTableName(dbTable.TableName);
            if (foundDBClass != null && foundDBClass.MappedTableID == null)
            {
                foundDBClass.MappedSchemaName = dbTable.SchemaName;
                foundDBClass.MappedDBTable = dbTable;
                UpdateClassDescription(dbTable, foundDBClass);
                return foundDBClass;
            }

            return CreateDMClass(dmSolution, dbTable);

        }

        private static void CheckSolution(IDMSolution dmSolution)
        {
            if (dmSolution == null) throw new ArgumentNullException("dmSolution");
            if (dmSolution.DefaultAssembly == null && dmSolution.Assemblies.Count > 0)
            {
                dmSolution.DefaultAssembly = dmSolution.Assemblies[0];
            }
            if (dmSolution.DefaultAssembly == null)
            {

                const string message =
                    "You cannot create a DM Importer if the Solution does not have a default assembly";
                throw new HabaneroDeveloperException(message, message);
            }
        }

        private void UpdateClassName(IDBTable dbTable, DMClass foundDBClass)
        {
            if (String.IsNullOrEmpty(foundDBClass.ClassNameBO)) foundDBClass.ClassNameBO = GetClassName(dbTable);
        }

        private DMClass CreateDMClass(IDMSolution dmSolution, IDBTable dbTable)
        {
            return new DMClass
                       {
                           MappedDBTable = dbTable,
                           MappedTableName = dbTable.TableName,
                           MappedSchemaName = dbTable.SchemaName,
                           ClassNameBO =  GetClassName(dbTable),
                           Assembly = dmSolution.DefaultAssembly,
                           ClassDescription = dbTable.TableComment
                       };
        }

        private string GetClassName(IDBTable dbTable)
        {
            return dbTable.GetClassName(TableNamePrefix, PrimaryKeyColumnSuffix);
        }

        private void UpdateClassDescription(IDBTable dbTable, DMClass mappedClass)
        {
            if (String.IsNullOrEmpty(mappedClass.ClassDescription)) mappedClass.ClassDescription = dbTable.TableComment;
        }
    }
}